//NOTE: this will be no neccesary if new Containers implements Ranges...

#ifndef category_adapter_HPP__
#define category_adapter_HPP__

#include <iterator>

#include "categories.hpp"
#include "ranges.hpp"

//template <typename Iterator>
//using IteratorCategory = typename std::iterator_traits<Iterator>::iterator_category;


namespace detail
{

	template <typename IteratorCategory>
	struct category_converter_dispatcher;

	template <>
	struct category_converter_dispatcher<std::input_iterator_tag>
	{
		typedef input_range_tag type;
	};

	template <>
	struct category_converter_dispatcher<std::output_iterator_tag>
	{
		typedef output_range_tag type;
	};

	template <>
	struct category_converter_dispatcher<std::forward_iterator_tag>
	{
		typedef forward_range_tag type;
	};

	template <>
	struct category_converter_dispatcher<std::bidirectional_iterator_tag>
	{
		typedef bidirectional_range_tag type;
	};

	template <>
	struct category_converter_dispatcher<std::random_access_iterator_tag>
	{
		typedef random_access_range_tag type;
	};



	//-------------------


	template <typename RangeCategory, typename ValueType>
	struct to_range_dispatcher;

	template <typename ValueType>
	struct to_range_dispatcher<input_range_tag, ValueType>
	{
		typedef input_range<ValueType> type;
	};

	//TODO:
	//template <typename ValueType>
	//struct to_range_dispatcher<output_range_tag, ValueType>
	//{
	//	typedef output_range<ValueType> type;
	//};

	//TODO:
	//template <typename ValueType>
	//struct to_range_dispatcher<forward_range_tag, ValueType>
	//{
	//	typedef forward_range<ValueType> type;
	//};

	template <typename ValueType>
	struct to_range_dispatcher<bidirectional_range_tag, ValueType>
	{
		typedef bidir_range<ValueType> type;
	};

	template <typename ValueType>
	struct to_range_dispatcher<random_access_range_tag, ValueType>
	{
		typedef random_access_range<ValueType> type;
	};

} //namespace detail

template <typename Iterator>
struct category_converter
{
	typedef typename detail::category_converter_dispatcher<
								typename std::iterator_traits<Iterator>::iterator_category
					>::type type;
};


template <typename Iterator>
struct to_range
{
	typedef typename detail::to_range_dispatcher<
		typename category_converter<Iterator>::type
		, typename std::iterator_traits<Iterator>::value_type
	>::type type;
};


template <typename Iterator>
using ToRange = typename to_range<Iterator>::type;


//test
/*
typedef typename category_converter< std::vector<int>::iterator >::type zzz;
std::cout << typeid(zzz).name() << std::endl;




//typedef typename to_range< std::vector<int>::iterator >::type range_type;
typedef ToRange< std::vector<int>::iterator > range_type;
std::cout << typeid(range_type).name() << std::endl;



*/

#endif // category_adapter_HPP__